using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.RecipeFramework.Extensions.CommonHelpers;

namespace Microsoft.Practices.RepositoryFactory.CodeGeneration.ObjectModel.NamingConventions
{
    /// <summary>
    /// Implements the <see cref="NamingStrategy"/> appropriately based on
    /// naming conventions for Oracle.
    /// </summary>
    public sealed class OracleNamingStrategy : NamingStrategy
    {
        private const string DELIMITERSTRING = "_";

        /// <summary>
        /// A common practice is to prefix parameters with &quot;P_.&quot;  If present 
        /// in sourceString it is removed by this method.
        /// </summary>
        /// <param name="sourceString"></param>
        /// <param name="delimiter"></param>
        /// <returns></returns>
        private string Rename(string sourceString, char delimiter)
        {
            if (String.IsNullOrEmpty(sourceString)) throw new ArgumentNullException("sourceString");

            string response = sourceString;

            if (sourceString.ToUpperInvariant().Contains(delimiter.ToString())) // added to address DB naming convention in use on my project
            {
                // All of this to go from P_JOB_TITLE to jobTitle
                String responseLowerCase = response.ToUpperInvariant().StartsWith("P_") ?
                    response.Substring(2).ToLowerInvariant() : response.ToLowerInvariant();
                Char[] delimiters = new Char[] { delimiter };
                String[] stringParts = responseLowerCase.Split(delimiters);
                System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder(response.Length);
                for (int i = 0; i < stringParts.Length; i++)
                {
                    if (i == 0)
                    {
                        // don't capitalize first letter
                        stringBuilder.Append(stringParts[i].Substring(0, 1));
                    }
                    else
                    {
                        // capitalize first letter
                        stringBuilder.Append(stringParts[i].Substring(0, 1).ToUpperInvariant());
                    }
                    stringBuilder.Append(stringParts[i].Substring(1));
                }
                response = stringBuilder.ToString();
            }

            return response;
        }


        public override string GetFieldName(string type)
        {
            string response = Rename(type, Char.Parse(DELIMITERSTRING));

            if (!String.IsNullOrEmpty(response))
            {
                response = "_" + response;
            }
            return response;
        }

        public override string GetMethodParameterName(string type)
        {
            string response = GetVariableName(type); 
            return Rename(response, Char.Parse(DELIMITERSTRING));
        }

        public override string GetPropertyName(string type)
        {
            string response = this.Rename(type, Char.Parse(DELIMITERSTRING));

            if (!String.IsNullOrEmpty(response))
            {
                response = response.Substring(0, 1).ToUpper() + response.Substring(1);
            }

            return response;
        }

        public override string GetVariableName(string type, bool convertToValidIdentifier)
        {
            string response = type;

            if (!String.IsNullOrEmpty(response))
            {
                response = response.Substring(0, 1).ToLower() + response.Substring(1);
                response = Rename(response, Char.Parse(DELIMITERSTRING));

                if (convertToValidIdentifier)
                {
                    response = CodeDomHelper.ConvertToValidIdentifier(response);
                }
            }

            return response;
        }
    }
}
